﻿#include "parametertreemodel.h"
#include "model/datamanager.h"
#include <QDebug>

const int CategoriesSize = 5; //一共五类    Attenuation = 0x0,Transducer,LimitLine,Frequency,Cal
/**
 * @brief ParameterTreeModel::ParameterTreeModel
 * @details 构造参数树模型并设置父对象。
 * @param parent Qt 父对象。
 */
ParameterTreeModel::ParameterTreeModel(QObject *parent)
    : QAbstractItemModel(parent)
{
}

/**
 * @brief ParameterTreeModel::~ParameterTreeModel
 * @details 析构参数树模型。
 */
ParameterTreeModel::~ParameterTreeModel()
{
}

/**
 * 当用户在视图中编辑数据时,此函数被调用
 * @brief ParameterTreeModel::setData
 * @details 处理叶子节点的重命名请求。
 * @param index 被编辑的模型索引。
 * @param value 新名称。
 * @param role 数据角色。
 * @return 成功返回 true。
 */
bool ParameterTreeModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    // 只处理编辑角色，并且只处理叶子节点
    if (role != Qt::EditRole || !index.isValid() || !index.parent().isValid()) {
        return false;
    }

    // 获取被修改项的概览信息
    OverviewItem overview = this->getOverview(index);
    QString newName = value.toString();

    //校验新名称
    if (newName.trimmed().isEmpty()) {
        qWarning() << "setData: New name cannot be empty.";
        return false;
    }

    if (overview.name == newName.trimmed()) {
        return false;
    }

    m_groupedData[static_cast<ParamTableKind>(index.parent().row())][index.row()].name = newName.trimmed();

    return true;
}

/**
 * @brief ParameterTreeModel::columnCount
 * @details 树模型仅使用单列表头。
 * @param parent 父索引。
 * @return 列数。
 */
int ParameterTreeModel::columnCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return 1;
}
/**
 * @brief ParameterTreeModel::hasChildren
 * @details 判断指定索引是否拥有子节点。
 * @param parent 父索引。
 * @return 有子节点返回 true。
 */
bool ParameterTreeModel::hasChildren(const QModelIndex &parent) const
{
    if (!parent.isValid()) {
        return true;
    }

    // 判断parent是不是一个顶层分类节点
    if (!parent.parent().isValid()) {
        // 是顶层分类节点。它是否有子节点，取决于对应的数据列表是否为空
        int categoryRow = parent.row();
        if (categoryRow >= 0 && categoryRow < CategoriesSize) {
            return !m_groupedData.value(static_cast<ParamTableKind>(categoryRow)).isEmpty();
        }
    }
    return false;
}

/**
 * @brief ParameterTreeModel::index
 * @details 创建给定行列的模型索引。
 * @param row 行索引。
 * @param column 列索引。
 * @param parent 父索引。
 * @return 创建的模型索引。
 */
QModelIndex ParameterTreeModel::index(int row, int column, const QModelIndex &parent) const
{
    if (!hasIndex(row, column, parent))
        return QModelIndex();

    // 如果父节点是无效的，说明请求的是顶层分类
    if (!parent.isValid()) {
        if (row >= CategoriesSize)
            return QModelIndex();
        // 为顶层分类创建索引。用行号作为内部ID。
        return createIndex(row, column, row + 1); // internalId不能为0
    }

    // 如果父节点是有效的，说明它是一个分类，请求的是它的子节点（具体的表）
    int parentRow = parent.row();
    if (parentRow >= CategoriesSize)
        return QModelIndex();

    const QList<OverviewItem> &items = m_groupedData.value(static_cast<ParamTableKind>(parentRow));

    if (row >= items.size())
        return QModelIndex();

    quintptr internalId = (quintptr)((parentRow + 1) << 16) | (quintptr)row;
    return createIndex(row, column, internalId);
}

/**
 * @brief ParameterTreeModel::parent
 * @details 返回指定索引的父节点索引。
 * @param index 当前索引。
 * @return 父索引或无效索引。
 */
QModelIndex ParameterTreeModel::parent(const QModelIndex &index) const
{
    if (!index.isValid())
        return QModelIndex();

    // 通过解析internalId来找到父节点
    quintptr internalId = index.internalId();
    int parentRow = (internalId >> 16) - 1;

    if (parentRow >= 0 && parentRow < CategoriesSize) {
        return createIndex(parentRow, 0, parentRow + 1);
    }

    return QModelIndex();
}

/**
 * @brief ParameterTreeModel::rowCount
 * @details 返回子节点数量。
 * @param parent 父索引。
 * @return 行数。
 */
int ParameterTreeModel::rowCount(const QModelIndex &parent) const
{
    if (!parent.isValid()) {
        return CategoriesSize;
    }

    if (!parent.parent().isValid()) {
        int categoryRow = parent.row();
        if (categoryRow >= 0 && categoryRow < CategoriesSize) {
            return m_groupedData.value(static_cast<ParamTableKind>(categoryRow)).size();
        }
    }
    return 0;
}

/**
 * @brief ParameterTreeModel::data
 * @details 提供树节点的显示或编辑数据。
 * @param index 模型索引。
 * @param role 数据角色。
 * @return 对应的值。
 */
QVariant ParameterTreeModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid()) {
        return QVariant();
    }

    //当视图请求“显示数据”或“编辑数据”时，都返回相同的内容
    if (role == Qt::DisplayRole || role == Qt::EditRole) {
        QModelIndex parent = index.parent();
        if (!parent.isValid()) {
            // 顶层分类节点
            return DataManager::instance()->getParamTableEnumString(static_cast<ParamTableKind>(index.row()));
        } else {
            // 叶子节点
            const ParamTableKind type = static_cast<ParamTableKind>(parent.row());
            if (m_groupedData.contains(type)) {
                const auto &items = m_groupedData.value(type);
                if (index.row() < items.size()) {
                    // 假设你要编辑和显示的是 item 的 name
                    return items.at(index.row()).name;
                }
            }
        }
    }

    // 其他角色返回空
    return QVariant();
}

/**
 * @brief ParameterTreeModel::getNode
 * @details 根据索引构建节点信息。
 * @param index 模型索引。
 * @return 动态创建的节点指针。
 */
TreeNode *ParameterTreeModel::getNode(const QModelIndex &index) const
{
    if (!index.isValid())
        return nullptr;

    TreeNode *node = new TreeNode();
    QModelIndex parent = index.parent();
    if (!parent.isValid()) {
        node->isCategory = true;
        node->categoryType = static_cast<ParamTableKind>(index.row());
    } else {
        node->isCategory = false;
        node->categoryType = static_cast<ParamTableKind>(parent.row());
        node->overview = m_groupedData.value(node->categoryType).at(index.row());
    }
    return node;
}

/**
 * @brief ParameterTreeModel::addTable
 * @details (公共接口) 向模型中添加一个新的参数表项。
 *        这个函数会立即更新模型和关联的视图。
 *        新增参数表节点并通知视图。
 * @param overview 包含新表信息的OverviewItem，其ID可以是临时的（如-1）。
 * @return 指向新添加项的QModelIndex。如果添加失败，则返回无效的QModelIndex。
 */
QModelIndex ParameterTreeModel::addTable(const OverviewItem &overview)
{
    // 查找该类型对应的分类在 m_categories 列表中的行号
    int categoryRow = static_cast<int>(overview.type);
    if (overview.type == ParamTableKind::Default || categoryRow < 0 || categoryRow >= CategoriesSize) {
        qWarning() << "ParameterTreeModel::addTable: Cannot add item, unknown type:" << static_cast<int>(overview.type);
        return QModelIndex();
    }

    // 根据行号，为这个分类创建一个有效的父级 QModelIndex
    QModelIndex parentIndex = this->index(categoryRow, 0, QModelIndex());
    if (!parentIndex.isValid()) {
        return QModelIndex();
    }

    // 新项将被添加到该分类列表的末尾
    int newRow = m_groupedData[overview.type].size();

    // 通知视图，在'parentIndex'下的'newRow'位置插入一行
    beginInsertRows(parentIndex, newRow, newRow);

    //  在模型内部的数据结构中，真正地添加数据
    m_groupedData[overview.type].append(overview);

    //   完成插入操作，通知视图更新
    endInsertRows();

    qDebug() << "ParameterTreeModel: Added temporary item '" << overview.name
             << "' to category '" << (int)overview.type << "' at row" << newRow;

    return this->index(newRow, 0, parentIndex);
}

/**
 * @brief ParameterTreeModel::getOverview
 * @brief 根据给定的模型索引，获取其对应的概览数据。
 * @param index 要查询的项的模型索引。
 * @return 如果索引是一个有效的叶子节点，返回其OverviewItem；否则返回一个空的OverviewItem。
 */
OverviewItem ParameterTreeModel::getOverview(const QModelIndex &index) const
{
    // 只有叶子节点（具体的表）才有完整的OverviewItem
    if (!index.isValid() || !index.parent().isValid()) {
        // 如果索引无效，或者它是一个顶层分类节点（没有父节点），则返回空
        return {};
    }

    // 获取父级（分类）的信息
    QModelIndex parent = index.parent();
    int categoryRow = parent.row();
    if (categoryRow < 0 || categoryRow >= CategoriesSize) {
        return {};
    }
    ParamTableKind categoryType = static_cast<ParamTableKind>(categoryRow);
    //获取子项在分类列表中的行号
    int itemRow = index.row();

    // 从内部数据结构中查找并返回对应的OverviewItem
    if (m_groupedData.contains(categoryType)) {
        const QList<OverviewItem> &items = m_groupedData.value(categoryType);
        if (itemRow >= 0 && itemRow < items.size()) {
            return items.at(itemRow);
        }
    }
    return {};
}

/**
 * @brief ParameterTreeModel::findIndexById
 * @details 通过 ID 定位节点索引。
 * @param tableId 表 ID。
 * @param kind 表类型。
 * @return 匹配索引或无效索引。
 */
QModelIndex ParameterTreeModel::findIndexById(int tableId, ParamTableKind kind)
{
    //  检查 'kind' 是否存在于数据源中
    if (!m_groupedData.contains(kind)) {
        return QModelIndex(); // 该分类下没有任何表
    }

    // 获取该分类下的所有表项列表
    const QList<OverviewItem> &items = m_groupedData.value(kind);

    //遍历这个列表，查找具有匹配 ID 的项
    for (int row = 0; row < items.size(); ++row) {
        if (items.at(row).id == tableId) {
            //获取父节点（分类节点）的 QModelIndex
            int categoryRow = static_cast<int>(kind);
            QModelIndex parentIndex = this->index(categoryRow, 0, QModelIndex());
            if (!parentIndex.isValid()) {
                return QModelIndex();
            }

            //在该父节点下，为找到的行创建一个子节点的 QModelIndex
            return this->index(row, 0, parentIndex);
        }
    }

    return QModelIndex();
}

/**
 * @brief ParameterTreeModel::findIndexByName
 * @details 通过名称查找节点索引。
 * @param name 表名称。
 * @return 匹配索引或无效索引。
 */
QModelIndex ParameterTreeModel::findIndexByName(const QString &name)
{
    if (name.isEmpty()) {
        return QModelIndex();
    }
    for (ParamTableKind kind : m_groupedData.keys()) {
        // 获取该分类下的所有表项列表
        const QList<OverviewItem> &items = m_groupedData.value(kind);
        for (int row = 0; row < items.size(); ++row) {
            if (items.at(row).name == name) {
                // 获取父节点（分类节点）的 QModelIndex
                int categoryRow = static_cast<int>(kind);
                QModelIndex parentIndex = this->index(categoryRow, 0, QModelIndex());
                if (!parentIndex.isValid()) {
                    continue;
                }
                //在该父节点下，为找到的行创建一个子节点的 QModelIndex
                return this->index(row, 0, parentIndex);
            }
        }
    }
    return QModelIndex();
}

/**
 * @brief ParameterTreeModel::refresh
 * @details 从数据源重新加载树结构。
 */
void ParameterTreeModel::refresh()
{
    beginResetModel();
    m_groupedData.clear();
    const QList<OverviewItem> &list = DataManager::instance()->getParameterTableOverviews();

    for (const auto &overview : list) {
        m_groupedData[overview.type].append(overview);
    }
    endResetModel();
}

/**
 * @brief ParameterTreeModel::flags
 * @details 返回树节点的交互标志。
 * @param index 模型索引。
 * @return 标志集合。
 */
Qt::ItemFlags ParameterTreeModel::flags(const QModelIndex &index) const
{
    if (!index.isValid()) {
        return Qt::NoItemFlags;
    }

    // 默认标志：所有项都可用和可选
    Qt::ItemFlags defaultFlags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;

    // 如果是叶子节点，就增加“可编辑”标志
    // 通过检查它是否有父节点来判断它是不是叶子节点
    if (index.parent().isValid()) {
        defaultFlags |= Qt::ItemIsEditable;
    }

    return defaultFlags;
}

/**
 * @brief ParameterTreeModel::headerData
 * @details 返回表头显示文本。
 * @param section 列索引。
 * @param orientation 方向。
 * @param role 数据角色。
 * @return 表头内容。
 */
QVariant ParameterTreeModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if (orientation == Qt::Horizontal && role == Qt::DisplayRole && section == 0)
        return "参数表";
    return QVariant();
}
